#!/bin/sh
#------------------------------------------------------------------------------
# =========                 |
# \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
#  \\    /   O peration     |
#   \\  /    A nd           | www.openfoam.com
#    \\/     M anipulation  |
#------------------------------------------------------------------------------
#     Copyright (C) 2011-2016 OpenFOAM Foundation
#     Copyright (C) 2019-2020 OpenCFD Ltd.
#------------------------------------------------------------------------------
# License
#     This file is part of OpenFOAM, distributed under GPL-3.0-or-later.
#
# Script
#     wmake/wmakeLnInclude
#
# Usage
#     wmakeLnInclude [OPTION] [-pwd | dir [.. dirN]]
#
# Description
#     Link source files in the specified dir(s) into their respective
#     lnInclude directories
#
#     C files:      .c .h
#     C++ files:    .C .cc .cpp .cxx .H .hh .hpp .hxx
#
#------------------------------------------------------------------------------
Script="${0##*/}"                   # Need 'Script' for wmakeFunctions messages
scriptsDir="${0%/*}"/scripts        # wmake/scripts directory
. "$scriptsDir"/wmakeFunctions      # Source wmake functions

printHelp() {
    cat<<USAGE

Usage: ${0##*/} [OPTION] [-pwd | dir [.. dirN]]

options:
  -f | -force       Force remove of existing lnInclude before recreating
  -u | -update      Update existing lnInclude directories
  -s | -silent      Silent mode (do not echo command)
  -pwd              Locate root directory containing Make/ directory
  -help             Print the usage

Link source files in specified dir(s) into their respective
lnInclude directories. With '-update', items are relinked with 'ln -sf'

USAGE
    exit 0 # clean exit
}


# Report error and exit
die()
{
    exec 1>&2
    echo
    echo "Error encountered:"
    while [ "$#" -ge 1 ]; do echo "    $1"; shift; done
    echo
    echo "See '${0##*/} -help' for usage"
    echo
    exit 1
}


#------------------------------------------------------------------------------
# Parse arguments and options
#------------------------------------------------------------------------------

# Option for 'ln'
optLink="-s"

unset optForce optUpdate optPwd

while [ "$#" -gt 0 ]
do
    case "$1" in
        -h | -help*)
            printHelp
            ;;
        -f | -force)
            optForce=true
            optLink="-sf"
            ;;
        -u | -update)
            optUpdate=true
            optLink="-sf"
            ;;
        -s | -silent | -quiet)
            export WM_QUIET=true
            ;;
        -pwd)
            optPwd=true
            ;;
        -*)
            die "unknown option: '$1'"
            ;;
        *)
            break
            ;;
    esac
    shift
done

[ "$optPwd" = true ] || [ "$#" -ge 1 ] || \
    die "incorrect number of arguments"

#------------------------------------------------------------------------------

baseDir="$1"

# With -pwd, go on discovery
if [ "$optPwd" = true ]
then
    if [ -n "$baseDir" ]
    then
        dir="$baseDir"
        if [ -d "$dir" ]
        then
            dir="${dir%/}"
        elif [ -f "$dir" ]
        then
            dir="${dir%/*}"
            : "${dir:=.}"
            [ "$dir" != "$baseDir" ] || dir="."
        else
            echo "$Script error: not a file or directory" 1>&2
            exit 1
        fi

        cd "$dir" 2>/dev/null || {
            echo "$Script error: could not change to directory '$dir'" 1>&2
            exit 1
        }
    fi

    # Locate target with Make/ directory
    if dir="$(findTarget .)"
    then
        baseDir="$(cd "$dir" && pwd -L)"
    else
        exit 2
    fi

    echo "Using $baseDir" 1>&2

    set -- "$baseDir"
fi


unset errorCode

for baseDir
do

    # Correct path/dir/lnInclude to something more sensible
    while [ "${baseDir##*/}" = lnInclude ]
    do
        baseDir="${baseDir%/*}"
        if [ "$baseDir" = lnInclude ]
        then
            baseDir="."
        fi
    done

    [ -d "$baseDir" ] || {
        echo "$Script error: base directory $baseDir does not exist" 1>&2
        errorCode=2
        continue
    }

    incDir="$baseDir/lnInclude"

    if [ "$optForce" = true ]
    then
        rm -rf -- "$incDir"
        mkdir "$incDir"
    elif [ -d "$incDir" ]
    then
        if [ "$optUpdate" != true ]
        then
            continue
        fi
    else
        mkdir "$incDir"
    fi

    if [ -d "$incDir" ]
    then
    (
        cd "$incDir" || {
            errorCode=1
            exit 1
        }

        # Display compact info
        echo "    ln: $incDir" 1>&2

        # Remove any broken links first
        # - helps if file locations have moved

        case "$WM_ARCH" in
        (darwin*)
            # -exec rm (not -delete) to remove names with '/' in their name
            # with \+ instead of \; to pack into a single command
            find -L . -type l -exec rm -- {} \+
            ;;
        (*)
            find -L . -type l -delete
            ;;
        esac

        # Create links, avoid recreating links unless necessary
        # things in the 'noLink' directory are skipped

        find .. \
            \( -name lnInclude -o -name Make -o -name config -o -name noLink \) \
            -prune \
            -o \( \
                -name '*.[CHch]' \
                -o -name '*.cc' \
                -o -name '*.hh' \
                -o -name '*.[ch]xx' \
                -o -name '*.[ch]pp' \
                -o -name '*.type' \
            \)  \
            -exec ln "$optLink" {} . \;
    )
    else
        echo "$Script error: failed to create include directory $incDir" 1>&2
    fi
done

exit "${errorCode:-0}"  # clean exit

#------------------------------------------------------------------------------
